import { Context } from 'koa';
import { AppContext } from '@/types';
import { SystemConfig } from '@/models';
import * as response from '@/utils/response';
import { validate, commonSchemas } from '@/utils/validator';
import logger from '@/utils/logger';
import Joi from 'joi';
import { Op } from 'sequelize';

/**
 * 系统配置控制器
 */
class SystemConfigController {
  /**
   * 获取配置
   */
  async get(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { key } = ctx.params;

    try {
      const config = await SystemConfig.findOne({
        where: {
          configKey: key,
          tenantId: appCtx.state.user!.tenantId as any,
        },
      });

      if (!config) {
        // 尝试获取全局配置
        const globalConfig = await SystemConfig.findOne({
          where: {
            configKey: key,
            tenantId: { [Op.is]: null } as any,
          },
        });

        if (!globalConfig) {
          return response.error(ctx, '配置不存在', 404);
        }

        response.success(ctx, this.parseConfigValue(globalConfig));
        return;
      }

      response.success(ctx, this.parseConfigValue(config));
    } catch (error) {
      logger.error('获取配置失败:', error);
      ctx.throw(500, '获取配置失败');
    }
  }

  /**
   * 获取所有配置
   */
  async list(ctx: Context) {
    const appCtx = ctx as AppContext;

    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      keyword: Joi.string().allow('').optional(),
    });

    const params = await validate<any>(ctx.query as any, schema);

    try {
      // 查询全局配置和当前租户的配置
      const where: any = {
        [Op.or]: [
          { tenantId: { [Op.is]: null } }, // 全局配置
          { tenantId: appCtx.state.user!.tenantId }, // 租户配置
        ],
      };

      if (params.keyword) {
        where.configKey = {
          [Op.like]: `%${params.keyword}%`,
        };
      }

      const { rows, count } = await SystemConfig.findAndCountAll({
        where,
        limit: params.pageSize,
        offset: (params.page - 1) * params.pageSize,
        order: [['createdAt', 'DESC']],
      });

      const list = rows.map((config) => this.parseConfigValue(config));

      response.success(ctx, {
        list,
        pagination: {
          page: params.page,
          pageSize: params.pageSize,
          total: count,
          totalPages: Math.ceil(count / params.pageSize),
        },
      });
    } catch (error) {
      logger.error('获取配置列表失败:', error);
      ctx.throw(500, '获取配置列表失败');
    }
  }

  /**
   * 设置/更新配置
   */
  async set(ctx: Context) {
    const appCtx = ctx as AppContext;

    const schema = Joi.object({
      configKey: Joi.string().max(100).required(),
      configValue: Joi.any().required(),
      configType: Joi.string().valid('string', 'number', 'boolean', 'json').optional(),
      description: Joi.string().max(500).optional().allow(''),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      // 转换配置值为字符串
      let configValue = data.configValue;
      if (typeof configValue !== 'string') {
        configValue = String(configValue);
      }
      
      // 文件存储相关配置为全局配置（tenantId = null）
      const isGlobalConfig = data.configKey.startsWith('file.');
      const tenantId = isGlobalConfig ? null : appCtx.state.user!.tenantId;
      
      // 先查找是否存在
      const existingConfig = await SystemConfig.findOne({
        where: {
          configKey: data.configKey,
          tenantId: { [Op.is]: tenantId } as any,
        },
      });

      let config: SystemConfig;
      if (existingConfig) {
        // 更新已有配置
        await existingConfig.update({
          configValue,
          configType: data.configType || 'string',
          description: data.description || '',
        });
        config = existingConfig;
      } else {
        // 创建新配置
        config = await SystemConfig.create({
          tenantId,
          configKey: data.configKey,
          configValue,
          configType: data.configType || 'string',
          description: data.description || '',
          isSystem: isGlobalConfig,
        } as any);
      }

      logger.info(
        `配置${existingConfig ? '更新' : '创建'}成功: ${data.configKey} by ${appCtx.state.user!.email}`
      );
      response.success(ctx, this.parseConfigValue(config as any), `配置${existingConfig ? '更新' : '创建'}成功`);
    } catch (error) {
      logger.error('设置配置失败:', error);
      ctx.throw(500, '设置配置失败');
    }
  }

  /**
   * 批量设置配置
   */
  async batchSet(ctx: Context) {
    const appCtx = ctx as AppContext;

    const schema = Joi.object({
      configs: Joi.array()
        .items(
          Joi.object({
            configKey: Joi.string().max(100).required(),
            configValue: Joi.any().required(),
            configType: Joi.string().valid('string', 'number', 'boolean', 'json').optional(),
            description: Joi.string().max(500).optional().allow(''),
          })
        )
        .min(1)
        .required(),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      const results = [];

      for (const configData of data.configs) {
        // 转换配置值为字符串
        let configValue = configData.configValue;
        if (typeof configValue !== 'string') {
          configValue = String(configValue);
        }
        
        // 文件存储相关配置为全局配置（tenantId = null）
        const isGlobalConfig = configData.configKey.startsWith('file.');
        const tenantId = isGlobalConfig ? null : appCtx.state.user!.tenantId;
        
        // 先查找是否存在
        const existingConfig = await SystemConfig.findOne({
          where: {
            configKey: configData.configKey,
            tenantId: { [Op.is]: tenantId } as any,
          },
        });

        let config: SystemConfig;
        if (existingConfig) {
          // 更新已有配置
          await existingConfig.update({
            configValue,
            configType: configData.configType || 'string',
            description: configData.description || '',
          });
          config = existingConfig;
        } else {
          // 创建新配置
          config = await SystemConfig.create({
            tenantId,
            configKey: configData.configKey,
            configValue,
            configType: configData.configType || 'string',
            description: configData.description || '',
            isSystem: isGlobalConfig,
          } as any);
        }

        results.push(this.parseConfigValue(config as any));
      }

      logger.info(`批量设置配置成功: ${data.configs.length} 个 by ${appCtx.state.user!.email}`);
      response.success(ctx, results, '批量设置配置成功');
    } catch (error: any) {
      logger.error('批量设置配置失败:', error);
      logger.error('错误详情:', error.message);
      logger.error('错误堆栈:', error.stack);
      ctx.throw(500, `批量设置配置失败: ${error.message}`);
    }
  }

  /**
   * 删除配置
   */
  async delete(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { key } = ctx.params;

    try {
      const config = await SystemConfig.findOne({
        where: {
          configKey: key,
          tenantId: appCtx.state.user!.tenantId as any,
        },
      });

      if (!config) {
        return response.error(ctx, '配置不存在', 404);
      }

      if (config.isSystem) {
        return response.error(ctx, '系统配置不能删除', 403);
      }

      await config.destroy();

      logger.info(`配置删除成功: ${key} by ${appCtx.state.user!.email}`);
      response.success(ctx, null, '配置删除成功');
    } catch (error) {
      logger.error('删除配置失败:', error);
      ctx.throw(500, '删除配置失败');
    }
  }

  /**
   * 解析配置值
   */
  private parseConfigValue(config: SystemConfig): any {
    const result: any = {
      id: config.id,
      tenantId: config.tenantId,
      configKey: config.configKey,
      configType: config.configType,
      description: config.description,
      isSystem: config.isSystem,
      createdAt: config.createdAt,
      updatedAt: config.updatedAt,
    };

    try {
      switch (config.configType) {
        case 'number':
          result.configValue = Number(config.configValue);
          break;
        case 'boolean':
          result.configValue = config.configValue === 'true';
          break;
        case 'json':
          result.configValue = JSON.parse(config.configValue || '{}');
          break;
        default:
          result.configValue = config.configValue;
      }
    } catch (error) {
      result.configValue = config.configValue;
    }

    return result;
  }

}

export default new SystemConfigController();

